package singsong;

import java.io.File;
import java.io.IOException;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException;

public class RegularAudioInputStream {

	public RegularAudioInputStream(String filename) {
		openFile(filename);
	}
	
	private void openFile(String filename) {
		try {
			audioInputStream = AudioSystem.getAudioInputStream(new File(filename));
			audioFormat = audioInputStream.getFormat();
			System.out.println(audioFormat);
			if (!audioFormat.getEncoding().equals(AudioFormat.Encoding.PCM_SIGNED)) {
				System.err.println("Audio file format must be PCM_SIGNED.");
			}
			frameBytes = new byte[audioFormat.getFrameSize()];
			frameDuration = 1.0f / audioFormat.getSampleRate();
		} catch (UnsupportedAudioFileException e) {
			System.err.println("Unrecognized audio file format.");
		} catch (IOException e) {
			System.err.println("Unable to read from audio file.");
		}
	}
	
	public float getTimePos() {
		return frame * frameDuration;
	}
	
	public float getSamplesPerSecond() {
		return audioFormat.getSampleRate();
	}
	
	public float getSampleDuration() {
		return frameDuration;
	}
	
	public AudioFormat getFormat() {
		return audioFormat;
	}
	
	public float nextSample() {
		if (readNextFrame()) {
			++frame;
			int bytesPerSample = audioFormat.getSampleSizeInBits() / 8;
			if (bytesPerSample == 1) {
				return frameBytes[0] / (float) Byte.MAX_VALUE;
			} else if (bytesPerSample == 2) {
				if (audioFormat.isBigEndian()) {
					return ((((int) frameBytes[1]) & 0xFF) | (((int) frameBytes[0]) << 8)) / (float) Short.MAX_VALUE;
				} else {
					return ((((int) frameBytes[0]) & 0xFF) | (((int) frameBytes[1]) << 8)) / (float) Short.MAX_VALUE;
				}
			}
		}
		return 0.0f;
	}
	
	public boolean isEndOfStream() {
		return endOfStream;
	}
	
	private boolean readNextFrame() {
		try {
			int bytesRead = audioInputStream.read(frameBytes, 0, audioFormat.getFrameSize());
			if (bytesRead == audioFormat.getFrameSize()) {
				return true;
			} else if (bytesRead == -1) {
				endOfStream = true;
			}
		} catch (IOException e) {
			System.err.println("Unable to read from audio file.");
		}
		return false;
	}
	
	private AudioInputStream audioInputStream;
	private AudioFormat audioFormat;
	private byte[] frameBytes;
	private float frameDuration;
	private int frame = 0;
	private boolean endOfStream = false;
}
